package com.cls.business.service.impl;

import com.cls.business.entity.*;
import com.cls.business.mapper.DeclarePlanMapper;
import com.cls.business.mapper.EntrustTopicMapper;
import com.cls.business.service.*;
import com.cls.common.enums.DictEnum;
import com.cls.system.entity.Configure;
import com.cls.system.service.IConfigureService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@RequiredArgsConstructor
public class ClassifyTopicService implements IClassifyTopicService {

    private final static Logger LOG = LoggerFactory.getLogger(ClassifyTopicService.class);


    @Autowired
    private IConfigureService configureService;

    @Autowired
    private ITopicService topicService;

    @Autowired
    private IEntrustTopicService entrustTopicService;
    @Autowired
    private EntrustTopicMapper entrustTopicMapper;

    @Autowired
    private ITopicPlanService topicPlanService;

    @Autowired
    private IDeclareTopicService declareTopicService;

    @Autowired
    private DeclarePlanMapper declarePlanMapper;


    public void classifyTopic(TopicPlan topicPlan){
        Topic topic = new Topic();
        topic.setPlanId(topicPlan.getPlanId());
        List<Topic> topics = topicService.getPublishedTopics(topic);
        Configure configure = configureService.getById(topicPlan.getConfigureId());
        int expertNum = 3;
        double proportion = 0;
        // 每组专家数、学科分类占比
        if(configure != null){
            expertNum = configure.getExpertNum();
            proportion = configure.getProportion();
        }

        List<DeclareTopic> declareTopics = new ArrayList();
        List<TopicSubjectDetail> totalDetails = new ArrayList();
        for (Topic one:topics){
            List<TopicSubjectDetail> details = declareTopicService.countDeclareTopicsBySubjectType(one.getTopicId(), DictEnum.CHECK_PASSED.getCode());
            List<String> subjectTypes = getValidSubjectType(details, expertNum, proportion);
            if(details != null && details.size() > 0){
                totalDetails.addAll(details);
                List<DeclareTopic> modifySubjects = modifySubjectType(subjectTypes, one.getTopicId());
                if(modifySubjects != null){
                    declareTopics.addAll(modifySubjects);
                }
                one.setSubjectTypeCodes(subjectTypes);
            }
            one.setStatusTypeCode(DictEnum.PLAN_CHECK.getCode());
        }

        topicService.autoWriteSubjectType(topics, declareTopics,totalDetails);
        topicPlanService.updateTopicPlanStatusCode(topicPlan);
        // 结束未申报的课题
        DeclarePlan param = new DeclarePlan();
        param.setPlanId(topicPlan.getPlanId());
        List<DeclarePlan> declarePlans = declarePlanMapper.selectDeclarePlansByPlanId(topicPlan.getPlanId());
        for(DeclarePlan declarePlan:declarePlans) {
            DeclareTopic declareTopic = declareTopicService.getById(declarePlan.getDeclareId());
            if(DictEnum.NO_APPLY.getCode().equals(declareTopic.getStatusTypeCode()) ||
                    DictEnum.PRE_APPLY.getCode().equals(declareTopic.getStatusTypeCode())){
                declareTopic.setIsFinish(true);
                declareTopicService.updateById(declareTopic);
            }
        }
    }

    public void classifyEntrustTopic(TopicPlan topicPlan){
        if(topicPlan == null){
            throw new IllegalArgumentException("参数异常！");
        }
        List<EntrustTopic> topics = entrustTopicMapper.selectByPlanId(topicPlan.getPlanId());
        Configure configure = configureService.getById(topicPlan.getConfigureId());
        int expertNum = 3;
        double proportion = 0;
        // 每组专家数、学科分类占比
        if(configure != null){
            expertNum = configure.getExpertNum();
            proportion = configure.getProportion();
        }

        List<DeclareTopic> declareTopics = new ArrayList();
        List<TopicSubjectDetail> totalDetails = new ArrayList();
        for (EntrustTopic one:topics){
            List<TopicSubjectDetail> details = declareTopicService.countDeclareTopicsBySubjectType(one.getTopicId(), DictEnum.CONCLUDE_ASSIGN.getCode());
            List<String> subjectTypes = getValidSubjectType(details, expertNum, proportion);
            if(details != null && details.size() > 0){
                totalDetails.addAll(details);
                List<DeclareTopic> modifySubjects = modifySubjectType(subjectTypes, one.getTopicId());
                if(modifySubjects != null){
                    declareTopics.addAll(modifySubjects);
                }
                one.setSubjectTypeCodes(subjectTypes);
            }
            one.setStatusTypeCode(DictEnum.PLAN_ASSIGN.getCode());
        }

        entrustTopicService.autoWriteSubjectType(topics, declareTopics,totalDetails);
        topicPlanService.updateTopicPlanStatusCode(topicPlan);

    }




    private List<DeclareTopic> modifySubjectType(List<String> subjectTypes, long topicId){
        if(subjectTypes == null || subjectTypes.size() < 1){
            return null;
        }
        String firstSubject = subjectTypes.get(0);
        DeclareTopic param = new DeclareTopic();
        param.setTopicId(topicId);
        List<DeclareTopic> declareTopics = declareTopicService.findDeclareTopics(param);
        for(DeclareTopic one: declareTopics){
            if( !subjectTypes.contains(one.getSubjectTypeCode())){
                one.setCheckSubjectTypeCode(firstSubject);
            } else {
                one.setCheckSubjectTypeCode(one.getSubjectTypeCode());
            }
        }
        return declareTopics;
    }


    /**
     * 对申报的课题进行分组，筛查出满足条件的学科类型
     * @param details
     * @param expertNum
     * @param proportion
     * @return
     */
    private List<String> getValidSubjectType(List<TopicSubjectDetail> details, int expertNum, double proportion){
        List<String> subjectTypes = new ArrayList<>();
        if(details != null && details.size() > 0){
            double totalNum = 0;
            for(TopicSubjectDetail one : details){
                totalNum += one.getNum();
            }
            double referenceValue =  proportion / 100;
            int groupNum = details.size();
            if(details.size() > expertNum){
                groupNum = expertNum;
            }
            subjectTypes.add(details.get(0).getSubjectTypeCode());
            details.get(0).setChoose(true);
            for(int i = 1; i < groupNum; i++){
                TopicSubjectDetail detail = details.get(i);
                double curValue = detail.getNum()/totalNum;
                if(curValue >= referenceValue){
                    subjectTypes.add(detail.getSubjectTypeCode());
                    detail.setChoose(true);
                }
            }
        }
        return subjectTypes;
    }

}
